﻿using System;
using System.Data;

namespace Flagwind.Data
{
	/// <summary>
	/// 表示实现该接口的一个数据访问提供程序。
	/// </summary>
	public interface IDataProvider : IDisposable
	{
		#region 属性定义

		string Name
		{
			get;
			set;
		}

		/// <summary>
		/// 获取连接数据库用户的Id。
		/// </summary>
		string ConnectionUserId
		{
			get;
		}

		/// <summary>
		/// 获取数据访问提供者的类型。
		/// </summary>
		DataProviderType ProviderType
		{
			get;
		}

		/// <summary>
		/// 获取参数名的标识字符。
		/// </summary>
		string ParameterChar
		{
			get;
		}

		/// <summary>
		/// 在插入具有自增列的数据后，获取刚才自增列的数据的语句。
		/// </summary>
		string SelectIdentityText
		{
			get;
			set;
		}

		/// <summary>
		/// 获取执行 SQL 查询的超时时间，单位：秒。
		/// </summary>
		int CommandTimeOut
		{
			get;
		}

		/// <summary>
		/// 获取最近一次执行查询的所耗费的时间，单位：毫秒。
		/// </summary>
		long LastElapsedTime
		{
			get;
		}

		/// <summary>
		/// 数据库连接字符串。
		/// </summary>
		string ConnectionString
		{
			get;
			set;
		}

		/// <summary>
		/// 写入数据的连接字符串。
		/// </summary>
		string DataWriteConnectionString
		{
			get;
			set;
		}

		/// <summary>
		/// 数据操作的错误信息，请在每次查询后检查该信息。
		/// </summary>
		string ErrorMessage
		{
			get;
		}

		#endregion

		#region 获取方法

		#region GetParameter

		/// <summary>
		/// 获取一个新参数对象。
		/// </summary>
		/// <returns>特定于数据源的参数对象。</returns>
		IDataParameter GetParameter();

		/// <summary>
		/// 获取一个新参数对象。
		/// </summary>
		/// <param name="name">参数名字。</param>
		/// <param name="type">数据库数据类型。</param>
		/// <param name="size">字段大小。</param>
		/// <returns>特定于数据源的参数对象。</returns>
		IDataParameter GetParameter(string name, DbType type, int size);

		/// <summary>
		/// 获取一个新参数对象。
		/// </summary>
		/// <param name="name">参数名字。</param>
		/// <param name="type">>数据库数据类型。</param>
		/// <returns>特定于数据源的参数对象。</returns>
		IDataParameter GetParameter(string name, DbType type);

		/// <summary>
		/// 根据参数名和值返回参数一个新的参数对象。
		/// </summary>
		/// <param name="name">参数名。</param>
		/// <param name="value">参数值。</param>
		/// <returns>特定于数据源的参数对象。</returns>
		IDataParameter GetParameter(string name, object value);

		/// <summary>
		/// 获取一个新参数对象。
		/// </summary>
		/// <param name="name">参数名。</param>
		/// <param name="type">参数值。</param>
		/// <param name="size">参数大小。</param>
		/// <param name="direction">参数输出类型。</param>
		/// <returns>特定于数据源的参数对象。</returns>
		IDataParameter GetParameter(string name, DbType type, int size, ParameterDirection direction);

		/// <summary>
		/// 获取一个新参数对象。
		/// </summary>
		/// <param name="name">参数名。</param>
		/// <param name="type">参数类型。</param>
		/// <param name="size">参数值的长度。</param>
		/// <param name="direction">参数的输入输出类型。</param>
		/// <param name="precision">参数值参数的精度。</param>
		/// <param name="scale">参数的小数位位数。</param>
		/// <returns>特定于数据源的参数对象。</returns>
		IDataParameter GetParameter(string name, DbType type, int size, ParameterDirection direction, byte precision, byte scale);

		#endregion

		#region GetSchema

		/// <summary>
		/// 返回此 SqlConnection 的数据源的架构信息。
		/// </summary>
		/// <param name="collectionName">集合名称，可以为空。</param>
		/// <param name="restrictionValues">请求的架构的一组限制值，可以为空。</param>
		/// <returns>数据库架构信息表。</returns>
		DataTable GetSchema(string collectionName, string[] restrictionValues);

		#endregion

		#region GetConnection

		/// <summary>
		/// 获取数据库连接对象实例。
		/// </summary>
		/// <returns>数据库连接对象。</returns>
		IDbConnection GetConnection();

		/// <summary>
		/// 获取数据库连接对象实例。
		/// </summary>
		/// <param name="connectionString">连接字符串。</param>
		/// <returns>数据库连接对象</returns>
		IDbConnection GetConnection(string connectionString);

		#endregion

		#region GetDataAdapter

		/// <summary>
		/// 获取数据适配器实例。
		/// </summary>
		/// <returns>数据适配器。</returns>
		IDbDataAdapter GetDataAdapter(IDbCommand command);

		#endregion

		#region GetNativeDbTypeName

		/// <summary>
		/// 获取当前数据库类型的参数数据类型名称。
		/// </summary>
		/// <param name="parameter">参数实例。</param>
		/// <returns>参数数据类型名称。</returns>
		string GetNativeDbTypeName(IDataParameter parameter);

		#endregion

		#endregion

		#region 执行方法

		#region ExecuteNonQuery

		/// <summary>
		/// 执行不返回值的查询，如果此查询出现了错误并且设置 OnErrorThrow 属性为 是，将抛出错误；否则将返回 -1，此时请检查ErrorMessage属性；
		/// 如果此查询在事务中并且出现了错误，将根据 OnErrorRollback 属性设置是否自动回滚事务。
		/// </summary>
		/// <param name="sql">SQL 语句。</param>
		/// <returns>受影响的行数。</returns>
		int ExecuteNonQuery(string sql);

		/// <summary>
		/// 执行不返回值的查询，如果此查询出现了错误并且设置 OnErrorThrow 属性为 是，将抛出错误；否则将返回 -1，此时请检查ErrorMessage属性；
		/// 如果此查询在事务中并且出现了错误，将根据 OnErrorRollback 属性设置是否自动回滚事务。
		/// </summary>
		/// <param name="sql">SQL 语句。</param>
		/// <param name="commandType">命令类型。</param>
		/// <param name="parameters">参数数组。</param>
		/// <returns>受影响的行数。</returns>
		int ExecuteNonQuery(string sql, CommandType commandType, IDataParameter[] parameters);

		#endregion

		#region ExecuteScalar

		/// <summary>
		/// 执行返回单一值的查询。
		/// </summary>
		/// <param name="sql">SQL 语句。</param>
		/// <returns>查询结果。</returns>
		object ExecuteScalar(string sql);

		/// <summary>
		/// 执行返回单一值得查询
		/// </summary>
		/// <param name="sql">SQL 语句。</param>
		/// <param name="commandType">命令类型。</param>
		/// <param name="parameters">参数数组。</param>
		/// <returns>查询结果。</returns>
		object ExecuteScalar(string sql, CommandType commandType, IDataParameter[] parameters);

		#endregion

		#region ExecuteDataReader

		/// <summary>
		/// 返回单一行的数据阅读器。
		/// </summary>
		/// <param name="sql">SQL 语句。</param>
		/// <returns>数据阅读器。</returns>
		IDataReader ExecuteDataReaderWithSingleRow(string sql);

		/// <summary>
		/// 返回单一行的数据阅读器。
		/// </summary>
		/// <param name="sql">SQL 语句。</param>
		/// <param name="parameters">参数。</param>
		/// <returns>数据阅读器。</returns>
		IDataReader ExecuteDataReaderWithSingleRow(string sql, IDataParameter[] parameters);

		/// <summary>
		/// 根据查询返回数据阅读器对象，在非事务过程中，阅读完以后会自动关闭数据库连接。
		/// </summary>
		/// <param name="sql">SQL 语句。</param>
		/// <returns>数据阅读器。</returns>
		IDataReader ExecuteDataReader(string sql);

		/// <summary>
		/// 根据查询返回数据阅读器对象
		/// </summary>
		/// <param name="sql">SQL 语句。</param>
		/// <param name="behavior">对查询和返回结果有影响的说明。</param>
		/// <returns>数据阅读器。</returns>
		IDataReader ExecuteDataReader(string sql, CommandBehavior behavior);

		/// <summary>
		/// 根据查询返回数据阅读器对象，但不可随机读取行内数据。
		/// </summary>
		/// <param name="sql">SQL 语句。</param>
		/// <param name="commandType">命令类型。</param>
		/// <param name="parameters">参数数组。</param>
		/// <returns>数据阅读器。</returns>
		IDataReader ExecuteDataReader(string sql, CommandType commandType, IDataParameter[] parameters);

		/// <summary>
		/// 根据查询返回数据阅读器对象,可以顺序读取行内的大数据列。
		/// </summary>
		/// <param name="sql">SQL 语句。</param>
		/// <param name="commandType">命令类型。</param>
		/// <param name="parameters">参数数组。</param>
		/// <returns>数据阅读器。</returns>
		IDataReader ExecuteDataReaderSequentialAccess(string sql, CommandType commandType, IDataParameter[] parameters);

		/// <summary>
		/// 根据查询返回数据阅读器对象。
		/// </summary>
		/// <param name="sql">SQL 语句。</param>
		/// <param name="commandType">命令类型。</param>
		/// <param name="behavior">对查询和返回结果有影响的说明。</param>
		/// <param name="parameters">参数数组。</param>
		/// <returns>数据阅读器。</returns>
		IDataReader ExecuteDataReader(ref string sql, CommandType commandType, CommandBehavior behavior, ref IDataParameter[] parameters);

		#endregion

		#region ExecuteInsertQuery

		/// <summary>
		/// 执行插入数据的查询。
		/// </summary>
		/// <param name="sql">插入数据的SQL。</param>
		/// <param name="id">要传出的本次操作的新插入数据行的主键ID值。</param>
		/// <returns>本次查询受影响的行数。</returns>
		int ExecuteInsertQuery(string sql, ref object id);

		/// <summary>
		/// 执行插入数据的查询。
		/// </summary>
		/// <param name="sql">插入数据的SQL。</param>
		/// <param name="commandType">命令类型。</param>
		/// <param name="parameters">参数数组。</param>
		/// <param name="id">要传出的本次操作的新插入数据行的自增主键ID值，如果没有获取到，则为-1。</param>
		/// <returns>本次查询受影响的行数。</returns>
		int ExecuteInsertQuery(string sql, CommandType commandType, IDataParameter[] parameters, ref object id);

		#endregion

		#region ExecuteDataSet

		/// <summary>
		/// 执行返回数据集的查询。
		/// </summary>
		/// <param name="sql">SQL 语句。</param>
		/// <returns>数据集。</returns>
		DataSet ExecuteDataSet(string sql);

		/// <summary>
		/// 执行返回数据集的查询。
		/// </summary>
		/// <param name="sql">SQL 语句。</param>
		/// <param name="commandType">命令类型。</param>
		/// <param name="parameters">参数数组。</param>
		/// <returns>数据集。</returns>
		DataSet ExecuteDataSet(string sql, CommandType commandType, IDataParameter[] parameters);

		/// <summary>
		/// 执行返回数据架构的查询。
		/// </summary>
		/// <param name="sql">SQL 语句。</param>
		/// <param name="commandType">命令类型。</param>
		/// <param name="parameters">参数数组。</param>
		/// <returns>数据架构。</returns>
		DataSet ExecuteDataSetSchema(string sql, CommandType commandType, IDataParameter[] parameters);

		/// <summary>
		/// 执行查询,并返回具有数据架构的数据集(整个过程仅使用一次连接)。
		/// </summary>
		/// <param name="sql">SQL 语句</param>
		/// <param name="commandType">命令类型。</param>
		/// <param name="parameters">查询参数。</param>
		/// <returns>具有数据架构的数据集。</returns>
		DataSet ExecuteDataSetWithSchema(string sql, CommandType commandType, IDataParameter[] parameters);

		/// <summary>
		/// 执行查询,并以指定的(具有数据架构的)数据集来填充数据。
		/// </summary>
		/// <param name="sql">查询语句。</param>
		/// <param name="commandType">命令类型。</param>
		/// <param name="parameters">查询参数。</param>
		/// <param name="schemaDataSet">指定的(具有数据架构的)数据集。</param>
		/// <returns>具有数据的数据集。</returns>
		DataSet ExecuteDataSetWithSchema(string sql, CommandType commandType, IDataParameter[] parameters, DataSet schemaDataSet);

		#endregion

		#endregion

		#region 事务处理

		/// <summary>
		/// 打开连接并开启事务。
		/// </summary>
		void BeginTransaction();

		/// <summary>
		/// 开启事务并指定事务隔离级别。
		/// </summary>
		/// <param name="level">事务隔离级别。</param>
		void BeginTransaction(IsolationLevel level);

		/// <summary>
		/// 提交事务并关闭连接。
		/// </summary>
		void Commit();

		/// <summary>
		/// 回滚事务并关闭连接。
		/// </summary>
		void Rollback();

		#endregion

		#region SQL 处理

		/// <summary>
		/// 对 SQL 语句进行其它的处理，例如将 SqlServer 的字段名外的中括号替换成数据库特定的字符。
		/// 该方法会在执行查询前调用。
		/// </summary>
		/// <param name="sql">SQL 语句。</param>
		/// <returns>处理后的 SQL 语句。</returns>
		string PrepareSQL(string sql);

		#endregion
	}
}